import { Request } from "express";

import { Injectable, NestInterceptor, CallHandler, ExecutionContext } from "@nestjs/common";
import { map } from "rxjs/operators";

import { ENUM_ERROR, RestDto } from "qqlx-core";
import { byteToKB, getDefaultResponse } from "qqlx-cdk";

import { getRandomString } from "../lib/crypto";
import { Logger } from "../lib/log";

@Injectable()
export class ResponseInterceptor implements NestInterceptor {
  constructor() {}

  intercept(context: ExecutionContext, next: CallHandler) {
    const _req: Request = context.switchToHttp().getRequest();
    const start = Date.now();

    // 设置追踪信息
    const traceId = _req.header("qqlx-trace-id") || getRandomString(8);
    const traceIp = _req.header("qqlx-trace-ip") || "NoIP";
    const traceInfo: RestDto["traceInfo"] = { traceId, traceIp, action: _req.method, path: _req.path };

    // 将请求体设置成 dto { ...any, traceInfo }
    _req.body.dto = { ..._req.body.dto, traceInfo };
    const { visitorId, visitorType } = _req.body.dto;

    // 请求体
    const body = _req.body;
    const reqSize = byteToKB(Buffer.from(JSON.stringify(body)).length, 0);
    return next.handle().pipe(
      map((data: any) => {
        // 包装处理结果
        const result = getDefaultResponse<any>();
        result.code = ENUM_ERROR.SUCCESS;
        result.data = data;

        // 日志（业务结束）
        const duration = Date.now() - start;
        Logger.info({
          rest: {
            traceInfo: { ...traceInfo, action: `✅ ${traceInfo.action}` },
            visitorId,
            visitorType,
          },
          log: `耗时=${duration}ms，请求体积=${reqSize}KB`,
        });

        // 警告
        if (duration > 400) {
          Logger.warn({
            rest: {
              traceInfo: { ...traceInfo, action: `⚠️ ${traceInfo.action}` },
              visitorId,
              visitorType,
            },
            log: "本次请求时间过长",
          });
        }

        return result;
      }),
    );
  }
}
